﻿using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
/// <summary>
/// Title: CSVHandler
/// Author: Tweety
/// Company: Kernel-Box
/// Website: http://www.Kernel-Box.com
/// Created: 12/08/2012
/// Modified: 16/08/2012
/// Current Version: 1.5.0.1
/// </summary>
/// <remarks></remarks>

public class CSVHandler
{
    /// <summary>
    /// Properties required for the Handler
    /// </summary>
    private int Row { get; set; }
    private int Column { get; set; }
    private String Location { get; set; }
    private bool _ignoreheaders { get; set; }
    public bool IgnoreHeaders
    {
        get { return _ignoreheaders; }
        set { _ignoreheaders = value; }
    }

    /// <summary>
    /// Creating an instance without a parameter
    /// </summary>
    public CSVHandler()
    {
        throw new Exception("Cannot create an instance without a valid location set.");
    }

    /// <summary>
    /// Generating an instance with a string parameter
    /// </summary>
    /// <param name="Location">Location of the CSV file that is being handled.</param>
    public CSVHandler(String Location)
    {
        if (string.IsNullOrEmpty(Location))
        {
            throw new Exception("The location cannot be null.");
        }
        if (!File.Exists(Location))
        {
            throw new Exception("The file does not exist.");
        }
        this.Location = Location;
    }

    /// <summary>
    /// Method to add headers to the CSV file.
    /// </summary>
    /// <param name="Header">A string of headers in the correct format to add.</param>
    public void AddHeaders(String Header)
    {
        File.WriteAllText(Location, string.Format("{0}{1}{2}", Header, Environment.NewLine, File.ReadAllText(Location)));
    }

    /// <summary>
    /// Method to add headers to the CSV file.
    /// </summary>
    /// <param name="Headers">An array of headers to add.</param>
    public void AddHeaders(String[] Headers)
    {
        AddHeaders(string.Join(", ", Headers));
    }

    /// <summary>
    /// Removes the headers.
    /// </summary>
    public void RemoveHeaders()
    {
        List<String> Container = new List<String>();
        Container.AddRange(File.ReadAllLines(Location));
        Container.RemoveAt(0);
        File.WriteAllLines(Location, Container.ToArray());
    }

    /// <summary>
    /// Reads a row in the CSV table.
    /// </summary>
    /// <returns>Returns an array collection of the row.</returns>
    public String[] ReadRow()
    {
        List<String> Container = new List<String>();
        Container.AddRange(File.ReadAllLines(Location));
    
        if (_ignoreheaders)
        {
            Container.RemoveAt(0);
        }

        if (Container.Count == Row)
        {
            //End of file
            return new String[] { };
        }

        Row++;
        return Container.ToArray()[Row].Split(',');
    }

    /// <summary>
    /// Reads a column in the CSV table.
    /// </summary>
    /// <returns>Returns an array collection of the column.</returns>
    public String[] ReadColumn()
    {
        List<String> Container = new List<String>();
        List<String> Temp = new List<String>();
        Container.AddRange(File.ReadAllLines(Location));

        if (Container[0].Split(',').Length == Column)
        {
            //End of rows
            return new String[] { };
        }

        for (int i = 0; i < Container.Count; i++)
        {
            Temp.Add(Container[i].Split(',')[Column]);
        }
        Column++;
        return Temp.ToArray();
    }

    /// <summary>
    /// Inserts an array of rows in the CSV table.
    /// </summary>
    /// <param name="Row">A collection of items to insert into a new row.</param>
    public void InsertRow(String[] Row)
    {
        InsertRow(String.Join(",", Row));
    }

    /// <summary>
    /// Inserts a row into the CSV table.
    /// </summary>
    /// <param name="Row">A collection of items to insert into a new row.</param>
    public void InsertRow(String Row)
    {
        File.AppendAllText(Location, Row);
    }

    /// <summary>
    /// Insert a column into the CSV data.
    /// </summary>
    /// <param name="Column">The column data that is going to be inserted.</param>
    /// <param name="HasHeaders">If headers are included, it will skip them.</param>
    public void InsertColumn(String[] Column, Boolean HasHeaders = false)
    {
        //Need to fix this?
        //Need to include HasHeaders and skip 0 index
        List<String> Container = new List<String>();
        List<String> Temp = new List<String>();
        Container.AddRange(File.ReadAllLines(Location));
        for (int i = 0; i < Container.Count; i++)
        {
            for (int x = 0; x < Column.Length; x++) 
            {
                Temp.Add(string.Join(", ", new String[] {Container[i], Column[x]}));
            }
        }
        File.WriteAllLines(Location, Temp.ToArray());
    }

    /// <summary>
    /// Removes a row from the CSV file.
    /// </summary>
    /// <param name="Index">The row index to remove.</param>
    public void RemoveRow(Int32 Index)
    {
        List<String> Container = new List<String>();
        Container.AddRange(File.ReadAllLines(Location));
        Container.RemoveAt(Index);
        File.WriteAllLines(Location, Container.ToArray());
    }

    /// <summary>
    /// Removes a column from the CSV file.
    /// </summary>
    /// <param name="Index">The column index to remove.</param>
    public void RemoveColumn(Int32 Index)
    {
        List<String> Container = new List<String>();
        List<String> Temp = new List<String>();
        List<String> RemoveAt = new List<String>();
        Container.AddRange(File.ReadAllLines(Location));
        for (int i = 0; i < Container.Count; i++)
        {
            RemoveAt.AddRange(Container[i].Split(','));
            RemoveAt.RemoveAt(Index);
            Temp.Add(string.Join(", ", RemoveAt.ToArray())); RemoveAt.Clear();

            
        }
    }

    /// <summary>
    /// Gets the value of a cell within the CSV file.
    /// </summary>
    /// <param name="Row">The row index for the cell address.</param>
    /// <param name="Column">The column index for the cell address.</param>
    /// <returns></returns>
    public String GetValue(Int32 Row, Int32 Column)
    {
        return File.ReadAllLines(Location)[Row].Split(',')[Column];
    }


    /// <summary>
    /// Writesa cell value using the row and column.
    /// </summary>
    /// <param name="Row">The row index for the cell address.</param>
    /// <param name="Column">The column index for the cell address.</param>
    /// <param name="Value">The value of the cell.</param>
    public void WriteValue(Int32 Row, Int32 Column, String Value)
    {
        List<String> Container = new List<String>();
        List<String> ColumnHolder = new List<String>();
        Container.AddRange(File.ReadAllLines(Location));

        ColumnHolder.AddRange(Container[Row].Split(','));
        ColumnHolder.RemoveAt(Column); ColumnHolder.Insert(Column, Value);
        Container.RemoveAt(Row); Container.Insert(Row, string.Join(",", ColumnHolder.ToArray()));

        File.WriteAllLines(Location, Container.ToArray());
    }
}